package com.pnnd;

import com.pnnd.utils.CollectionUtils;
import com.pnnd.utils.NeedInit;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ObjectDTypeObject extends DTypeObject {

    private Class jvmClass;
    private List<DTypeObject> subTypes = new ArrayList<>();

    private List<DTypeObjectField> fields = new ArrayList<>();

    protected ObjectDTypeObject(String name, String typeStr, int typeNum) {
        super(name, typeStr, typeNum, -1);
    }

    protected ObjectDTypeObject() {
        super("object", "dtype.object", 8);
    }

    @Override
    public Class<?> getJvmKlass() {

        if(jvmClass == null)
            return Object.class;
        else
            return jvmClass;
    }

    @Override
    public NeedInit create() {
        return new ObjectDTypeObject();
    }

    @Override
    public List<DTypeObject> getSubTypes(){
        return CollectionUtils.readonly(subTypes);
    }

    public List<DTypeObjectField> getFields(){
        return CollectionUtils.readonly(fields);
    }

    public DTypeObject createSubType(DTypeObject ...fieldTypes){

        ObjectDTypeObject objectDTypeObject = new ObjectDTypeObject("self","object.self",this.typeNum * 1000 + this.subTypes.size() + 1);

        for(int i=0;i<fieldTypes.length;i++){
            DTypeObjectField field = new DTypeObjectField(String.valueOf(i),fieldTypes[i],objectDTypeObject);
            objectDTypeObject.fields.add(field);
        }

        this.elementLength = Arrays.stream(fieldTypes).map(s->s.getElementLength()).reduce((i,o)->i+o).get();

        this.name += this.elementLength;
        this.typeStr += this.elementLength;

        this.subTypes.add(objectDTypeObject);



        return objectDTypeObject;
    }

    public DTypeObject createSubType(Class klass){
        if(klass == null){
            throw new NullPointerException();
        }

        DTypeObject[] types = new DTypeObject[klass.getFields().length];

        for(int i=0;i<klass.getFields().length;i++){
            types[i] = NdEnvironment.getByJvmClass(klass.getFields()[i].getType());
        }


        ObjectDTypeObject dTypeObject = (ObjectDTypeObject)this.createSubType(types);

        dTypeObject.jvmClass = klass;
        dTypeObject.name = klass.getName();
        dTypeObject.typeStr = klass.getTypeName();

        NdEnvironment.classDTypeObjectMap.put(klass,dTypeObject);

        return dTypeObject;
    }
}
